package com.unproy.model.domain;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;


@Entity
@Table(name = "TBUSER")
public class User implements Serializable, Comparable<User> {
	private static final long	serialVersionUID	= 6006385228887108817L;
	private Integer				userId;
	private String				firstName;
	private String				middleName;
	private String				lastName;
	private String				username;
	private String				password;
	private String				email;
	private Set<Role>			roles				= new HashSet<Role>();
	private Set<Article>		createdArticles		= new HashSet<Article>();
	private Set<Article>		approvedArticles	= new HashSet<Article>();
	private Set<Article>		publishedArticles	= new HashSet<Article>();
	private Set<Media>			createdMedia		= new HashSet<Media>();
	private Set<Media>			approvedMedia		= new HashSet<Media>();
	private Set<Media>			publishedMedia		= new HashSet<Media>();
	private Set<Comment>		createdComments		= new HashSet<Comment>();
	private Set<Comment>		publishedComments	= new HashSet<Comment>();
	private Set<Comment>		approvedComments	= new HashSet<Comment>();
	
	@Id
	@SequenceGenerator(name = "userId", sequenceName = "SQUSER")
	@GeneratedValue(generator = "userId", strategy = GenerationType.SEQUENCE)
	@Column(name = "USERID", unique = true, nullable = false)
	public Integer getUserId() {
		return this.userId;
	}
	
	public void setUserId(Integer userId) {
		this.userId = userId;
	}
	
	@Column(name = "FSTNAM", nullable = false)
	public String getFirstName() {
		return this.firstName;
	}
	
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	
	@Column(name = "MIDNAM")
	public String getMiddleName() {
		return this.middleName;
	}
	
	public void setMiddleName(String middleName) {
		this.middleName = middleName;
	}
	
	@Column(name = "LSTNAM", nullable = false)
	public String getLastName() {
		return this.lastName;
	}
	
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	
	@Column(name = "USRNAM", nullable = false)
	public String getUsername() {
		return this.username;
	}
	
	public void setUsername(String username) {
		this.username = username;
	}
	
	@Column(name = "PASSWD", nullable = false)
	public String getPassword() {
		return this.password;
	}
	
	public void setPassword(String password) {
		this.password = password;
	}
	
	@Column(name = "USREML")
	public String getEmail() {
		return this.email;
	}
	
	public void setEmail(String email) {
		this.email = email;
	}
	
	@ManyToMany(fetch = FetchType.EAGER)
	@JoinTable(name = "TBUSRO", joinColumns = @JoinColumn(name = "USERID", nullable = false), inverseJoinColumns = @JoinColumn(name = "ROLEID", nullable = false))
	public Set<Role> getRoles() {
		return this.roles;
	}
	
	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "createdBy")
	public Set<Article> getCreatedArticles() {
		return this.createdArticles;
	}
	
	public void setCreatedArticles(Set<Article> createdArticles) {
		this.createdArticles = createdArticles;
	}
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "approvedBy")
	public Set<Article> getApprovedArticles() {
		return this.approvedArticles;
	}
	
	public void setApprovedArticles(Set<Article> approvedArticles) {
		this.approvedArticles = approvedArticles;
	}
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "publishedBy")
	public Set<Article> getPublishedArticles() {
		return this.publishedArticles;
	}
	
	public void setPublishedArticles(Set<Article> publishedArticles) {
		this.publishedArticles = publishedArticles;
	}
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "createdBy")
	public Set<Media> getCreatedMedia() {
		return this.createdMedia;
	}
	
	public void setCreatedMedia(Set<Media> createdMedia) {
		this.createdMedia = createdMedia;
	}
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "approvedBy")
	public Set<Media> getApprovedMedia() {
		return this.approvedMedia;
	}
	
	public void setApprovedMedia(Set<Media> approvedMedia) {
		this.approvedMedia = approvedMedia;
	}
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "publishedBy")
	public Set<Media> getPublishedMedia() {
		return this.publishedMedia;
	}
	
	public void setPublishedMedia(Set<Media> publishedMedia) {
		this.publishedMedia = publishedMedia;
	}
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "createdBy")
	public Set<Comment> getCreatedComments() {
		return this.createdComments;
	}
	
	public void setCreatedComments(Set<Comment> createdComments) {
		this.createdComments = createdComments;
	}
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "approvedBy")
	public Set<Comment> getApprovedComments() {
		return this.approvedComments;
	}
	
	public void setApprovedComments(Set<Comment> approvedComments) {
		this.approvedComments = approvedComments;
	}
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "publishedBy")
	public Set<Comment> getPublishedComments() {
		return this.publishedComments;
	}
	
	public void setPublishedComments(Set<Comment> comments) {
		this.publishedComments = comments;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((this.userId == null) ? 0 : this.userId.hashCode());
		result = prime * result + ((this.username == null) ? 0 : this.username.hashCode());
		return result;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		User other = (User) obj;
		if (this.userId == null) {
			if (other.userId != null)
				return false;
		} else if (!this.userId.equals(other.userId))
			return false;
		if (this.username == null) {
			if (other.username != null)
				return false;
		} else if (!this.username.equals(other.username))
			return false;
		return true;
	}
	
	@Override
	public int compareTo(User user) {
		return toString().compareTo(user.toString());
	}
	
	@Override
	public String toString() {
		return getLastName() + ", " + getFirstName() + (getMiddleName() != null ? getMiddleName().charAt(0) + "." : "");
	}
}
